#include "VulkanPipeline.h"
#include "VulkanContext.h"
#include "VulkanDevice.h"
#include "VulkanShader.h"
#include "Runtime/Allocator/Memory.h"
#include "Runtime/Misc/Crc.h"

namespace Alice
{
    static void GetVulkanGraphicsShaders(const FBoundShaderStateInput& inBoundShaderStateInput, VulkanShader* OutShaders[EShaderStage::SS_NumGraphicsStages])
    {
        Memory::Zero(OutShaders, EShaderStage::SS_NumGraphicsStages * sizeof(*OutShaders));
        OutShaders[0] = static_cast<VulkanVertexShader*>(inBoundShaderStateInput.mVertexShader);
        if (inBoundShaderStateInput.mPixelShader!=nullptr)
        {
            OutShaders[1] = static_cast<VulkanPixelShader*>(inBoundShaderStateInput.mPixelShader);
        }
        /*if (BSI.GetGeometryShader())
        {
#if VULKAN_SUPPORTS_GEOMETRY_SHADERS
            OutShaders[2] = ResourceCast(BSI.GetGeometryShader());
#else
            ensureMsgf(0, TEXT("Geometry not supported!"));
#endif
        }
        if (BSI.GetMeshShader())
        {
            OutShaders[3] = ResourceCast(BSI.GetMeshShader());
        }

        if (BSI.GetAmplificationShader())
        {
            OutShaders[4] = ResourceCast(BSI.GetAmplificationShader());
        }*/
    }
    VulkanGraphicsPipelineObjectKey::VulkanGraphicsPipelineObjectKey(const void* inGraphicsPipelineDescription)
    {
        VulkanGraphicsPipelineDescription* graphicsPipelineDescription=(VulkanGraphicsPipelineDescription*)inGraphicsPipelineDescription;
        mDataLen=sizeof(graphicsPipelineDescription->VertexInputKey);
        mDataLen+=sizeof(graphicsPipelineDescription->RasterizationSamples);
        mDataLen+=sizeof(graphicsPipelineDescription->ControlPoints);
        mDataLen+=sizeof(graphicsPipelineDescription->Topology);
        mDataLen+=graphicsPipelineDescription->ColorAttachmentStates.size()*sizeof(VulkanGraphicsPipelineDescription::FBlendAttachment);
        uint32 descriptorSetLayoutBindingTotalSize=0;
        for(uint32 i=0;i<graphicsPipelineDescription->DescriptorSetLayoutBindings.size();i++)
        {
            for(uint32 j=0;j<graphicsPipelineDescription->DescriptorSetLayoutBindings[i].size();j++)
            {
                descriptorSetLayoutBindingTotalSize+=sizeof(FDescriptorSetLayoutBinding);
            }
        }
        mDataLen+=descriptorSetLayoutBindingTotalSize;
        mDataLen+=graphicsPipelineDescription->VertexBindings.size()*sizeof(VulkanGraphicsPipelineDescription::FVertexBinding);
        mDataLen+=graphicsPipelineDescription->VertexAttributes.size()*sizeof(VulkanGraphicsPipelineDescription::FVertexAttribute);
        mDataLen+=sizeof(VulkanGraphicsPipelineDescription::FRasterizer);
        mDataLen+=sizeof(VulkanGraphicsPipelineDescription::FDepthStencil);
        mDataLen+=sizeof(graphicsPipelineDescription->ShaderKeys);
        mDataLen+=sizeof(graphicsPipelineDescription->ShaderKeyShared);
        mDataLen+=graphicsPipelineDescription->RenderTargets.GetSize();
        mDataLen+=sizeof(graphicsPipelineDescription->SubpassIndex);
        mDataLen+=sizeof(graphicsPipelineDescription->UseAlphaToCoverage);
        mDataLen+=sizeof(graphicsPipelineDescription->ShadingRate);
        mDataLen+=sizeof(graphicsPipelineDescription->Combiner);
        mData=new unsigned char[mDataLen];
        int32 dataOffset=0;
        unsigned char*dataDst=(unsigned char*)mData;
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->VertexInputKey,sizeof(graphicsPipelineDescription->VertexInputKey));
        dataOffset+=sizeof(graphicsPipelineDescription->VertexInputKey);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RasterizationSamples,sizeof(graphicsPipelineDescription->RasterizationSamples));
        dataOffset+=sizeof(graphicsPipelineDescription->RasterizationSamples);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->ControlPoints,sizeof(graphicsPipelineDescription->ControlPoints));
        dataOffset+=sizeof(graphicsPipelineDescription->ControlPoints);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->Topology,sizeof(graphicsPipelineDescription->Topology));
        dataOffset+=sizeof(graphicsPipelineDescription->Topology);
        for(uint32 i=0;i<graphicsPipelineDescription->ColorAttachmentStates.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->ColorAttachmentStates[i],sizeof(VulkanGraphicsPipelineDescription::FBlendAttachment));
            dataOffset+=sizeof(VulkanGraphicsPipelineDescription::FBlendAttachment);
        }
        for(uint32 i=0;i<graphicsPipelineDescription->DescriptorSetLayoutBindings.size();i++)
        {
            for(uint32 j=0;j<graphicsPipelineDescription->DescriptorSetLayoutBindings[i].size();j++)
            {
                memcpy(dataDst+dataOffset,&graphicsPipelineDescription->DescriptorSetLayoutBindings[i][j],sizeof(FDescriptorSetLayoutBinding));
                dataOffset+=sizeof(FDescriptorSetLayoutBinding);
            }
        }
        for(uint32 i=0;i<graphicsPipelineDescription->VertexBindings.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->VertexBindings[i],sizeof(VulkanGraphicsPipelineDescription::FVertexBinding));
            dataOffset+=sizeof(VulkanGraphicsPipelineDescription::FVertexBinding);
        }
        for(uint32 i=0;i<graphicsPipelineDescription->VertexAttributes.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->VertexAttributes[i],sizeof(VulkanGraphicsPipelineDescription::FVertexAttribute));
            dataOffset+=sizeof(VulkanGraphicsPipelineDescription::FVertexAttribute);
        }
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->Rasterizer,sizeof(graphicsPipelineDescription->Rasterizer));
        dataOffset+=sizeof(graphicsPipelineDescription->Rasterizer);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->DepthStencil,sizeof(graphicsPipelineDescription->DepthStencil));
        dataOffset+=sizeof(graphicsPipelineDescription->DepthStencil);
        memcpy(dataDst+dataOffset,graphicsPipelineDescription->ShaderKeys,sizeof(graphicsPipelineDescription->ShaderKeys));
        dataOffset+=sizeof(graphicsPipelineDescription->ShaderKeys);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->ShaderKeyShared,sizeof(graphicsPipelineDescription->ShaderKeyShared));
        dataOffset+=sizeof(graphicsPipelineDescription->ShaderKeyShared);
        for(uint32 i=0;i<graphicsPipelineDescription->RenderTargets.ColorAttachments.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.ColorAttachments[i],sizeof(graphicsPipelineDescription->RenderTargets.ColorAttachments[i]));
            dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.ColorAttachments[i]);
        }
        for(uint32 i=0;i<graphicsPipelineDescription->RenderTargets.ResolveAttachments.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.ResolveAttachments[i],sizeof(graphicsPipelineDescription->RenderTargets.ResolveAttachments[i]));
            dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.ResolveAttachments[i]);
        }
        for(uint32 i=0;i<graphicsPipelineDescription->RenderTargets.Descriptions.size();i++)
        {
            memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.Descriptions[i],sizeof(graphicsPipelineDescription->RenderTargets.Descriptions[i]));
            dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.Descriptions[i]);
        }
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.Depth,sizeof(graphicsPipelineDescription->RenderTargets.Depth));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.Depth);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.Stencil,sizeof(graphicsPipelineDescription->RenderTargets.Stencil));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.Stencil);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.FragmentDensity,sizeof(graphicsPipelineDescription->RenderTargets.FragmentDensity));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.FragmentDensity);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.StencilDescription,sizeof(graphicsPipelineDescription->RenderTargets.StencilDescription));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.StencilDescription);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.NumAttachments,sizeof(graphicsPipelineDescription->RenderTargets.NumAttachments));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.NumAttachments);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.NumColorAttachments,sizeof(graphicsPipelineDescription->RenderTargets.NumColorAttachments));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.NumColorAttachments);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.bHasDepthStencil,sizeof(graphicsPipelineDescription->RenderTargets.bHasDepthStencil));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.bHasDepthStencil);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.bHasResolveAttachments,sizeof(graphicsPipelineDescription->RenderTargets.bHasResolveAttachments));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.bHasResolveAttachments);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.bHasDepthStencilResolve,sizeof(graphicsPipelineDescription->RenderTargets.bHasDepthStencilResolve));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.bHasDepthStencilResolve);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.bHasFragmentDensityAttachment,sizeof(graphicsPipelineDescription->RenderTargets.bHasFragmentDensityAttachment));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.bHasFragmentDensityAttachment);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.NumUsedClearValues,sizeof(graphicsPipelineDescription->RenderTargets.NumUsedClearValues));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.NumUsedClearValues);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.RenderPassCompatibleHash,sizeof(graphicsPipelineDescription->RenderTargets.RenderPassCompatibleHash));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.RenderPassCompatibleHash);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->RenderTargets.Extent3D,sizeof(graphicsPipelineDescription->RenderTargets.Extent3D));
        dataOffset+=sizeof(graphicsPipelineDescription->RenderTargets.Extent3D);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->SubpassIndex,sizeof(graphicsPipelineDescription->SubpassIndex));
        dataOffset+=sizeof(graphicsPipelineDescription->SubpassIndex);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->UseAlphaToCoverage,sizeof(graphicsPipelineDescription->UseAlphaToCoverage));
        dataOffset+=sizeof(graphicsPipelineDescription->UseAlphaToCoverage);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->ShadingRate,sizeof(graphicsPipelineDescription->ShadingRate));
        dataOffset+=sizeof(graphicsPipelineDescription->ShadingRate);
        memcpy(dataDst+dataOffset,&graphicsPipelineDescription->Combiner,sizeof(graphicsPipelineDescription->Combiner));
        dataOffset+=sizeof(graphicsPipelineDescription->Combiner);
        mKey=Crc::MemCrc32(mData,mDataLen);
    }

    void FDescriptorSetLayoutBinding::ReadFrom(const VkDescriptorSetLayoutBinding& InState)
    {
        Binding =			InState.binding;
        ensure(InState.descriptorCount == 1);
        //DescriptorCount =	InState.descriptorCount;
        DescriptorType =	InState.descriptorType;
        StageFlags =		InState.stageFlags;
    }

    void FDescriptorSetLayoutBinding::WriteInto(VkDescriptorSetLayoutBinding& Out) const
    {
        Out.binding = Binding;
        //Out.descriptorCount = DescriptorCount;
        Out.descriptorType = (VkDescriptorType)DescriptorType;
        Out.stageFlags = StageFlags;
    }
    VulkanLayout::VulkanLayout(VulkanDevice* inDevice, bool inIsGraphicsLayout, bool inUseBindlessResources)
        :mDevice(inDevice),mbIsGraphicsLayout(inIsGraphicsLayout),mbUseBindlessResources(inUseBindlessResources)
    {
        
    }
    FVulkanCGIGraphicPipelineState::FVulkanCGIGraphicPipelineState(VulkanDevice* inDevice, const FGraphicsPipelineStateInitializer& PSOInitializer, const VulkanGraphicsPipelineDescription& Desc)
        :mDevice(inDevice),mVulkanGraphicsPipelineDescription(Desc)
    {
        
    }
    CGIGraphicsShader* FVulkanCGIGraphicPipelineState::GetShader(EShaderFrequency Frequency) const
    {
        return nullptr;
    }
    void FVulkanCGIGraphicPipelineState::Bind(VkCommandBuffer inCommandBuffer)const
    {
        vkCmdBindPipeline(inCommandBuffer,VK_PIPELINE_BIND_POINT_GRAPHICS,mPipeline);
    }

    FVulkanPipelineStateCacheManager::FVulkanPipelineStateCacheManager(VulkanDevice* inDevice)
        :mDevice(inDevice)
    {
        
    }
    void FVulkanPipelineStateCacheManager::CreateGraphicsEntry(const FGraphicsPipelineStateInitializer& PSOInitializer, FVulkanDescriptorSetsLayoutInfo& DescriptorSetLayoutInfo, VulkanGraphicsPipelineDescription* Desc)
    {
        FUniformBufferGatherInfo ubgi;
        DescriptorSetLayoutInfo.FinalizeBindings<false>(*mDevice,ubgi,nullptr,false);
    }
    CGIGraphicsPipelineState* FVulkanPipelineStateCacheManager::RHICreateGraphicsPipelineState(const FGraphicsPipelineStateInitializer& Initializer)
    {
        VulkanGraphicsPipelineDescription vulkanGraphicsPipelineDescription;
        FVulkanDescriptorSetsLayoutInfo descriptorSetLayoutInfo;
        CreateGraphicsEntry(Initializer,descriptorSetLayoutInfo,&vulkanGraphicsPipelineDescription);
        
        FVulkanCGIGraphicPipelineState*ret=new FVulkanCGIGraphicPipelineState(mDevice,Initializer,vulkanGraphicsPipelineDescription);
        
        ret->mLayout=new VulkanLayout(mDevice,true,false);
        ret->mLayout->mDescriptorSetsLayout.Hash=descriptorSetLayoutInfo.Hash;
        ret->mRenderPass=mDevice->GetImmediateContext().PrepareRenderPassForPSOCreation(Initializer);
        VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
        pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
        pipelineLayoutCreateInfo.setLayoutCount = 0;
        vkCreatePipelineLayout(mDevice->GetDevice(),&pipelineLayoutCreateInfo,nullptr,&ret->mLayout->mPipelineLayout);
        VulkanShader* shaders[EShaderStage::SS_NumGraphicsStages];
        GetVulkanGraphicsShaders(Initializer.mBoundShaderStateInput,shaders);
        CreateGraphicsPipelineFromEntry(ret,shaders,FGraphicsPipelineStateInitializer::EPSOPrecacheCompileType::NormalPri);
        return ret;
    }
    bool FVulkanPipelineStateCacheManager::CreateGraphicsPipelineFromEntry(FVulkanCGIGraphicPipelineState* PSO, VulkanShader* inShaders[5], FGraphicsPipelineStateInitializer::EPSOPrecacheCompileType PSOCompileType)
    {
        VkPipeline* Pipeline = &PSO->mPipeline;
        VkGraphicsPipelineCreateInfo PipelineInfo;
        ZeroVulkanStruct(PipelineInfo, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
        VkVertexInputBindingDescription vertexInputBindingDescription = {};
        vertexInputBindingDescription.binding = 0;//0 slot ->
        vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
        vertexInputBindingDescription.stride = 3 * sizeof(float);

        VkVertexInputAttributeDescription vertexInputAttributeDescription[4];
        vertexInputAttributeDescription[0].binding = 0;
        vertexInputAttributeDescription[0].location = 0;
        vertexInputAttributeDescription[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;//vec4
        vertexInputAttributeDescription[0].offset = 0;

        vertexInputAttributeDescription[1].binding = 0;
        vertexInputAttributeDescription[1].location = 1;
        vertexInputAttributeDescription[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;//vec4
        vertexInputAttributeDescription[1].offset = sizeof(float)*4;

        vertexInputAttributeDescription[2].binding = 0;
        vertexInputAttributeDescription[2].location = 2;
        vertexInputAttributeDescription[2].format = VK_FORMAT_R32G32B32A32_SFLOAT;//vec4
        vertexInputAttributeDescription[2].offset = sizeof(float) * 8;

        vertexInputAttributeDescription[3].binding = 0;
        vertexInputAttributeDescription[3].location = 3;
        vertexInputAttributeDescription[3].format = VK_FORMAT_R32G32B32A32_SFLOAT;//vec4
        vertexInputAttributeDescription[3].offset = sizeof(float) * 12;

        VkPipelineVertexInputStateCreateInfo pipelinVertexInputStateCreateInfo = {};
        //pos,texcoord,normal,tangent|pos,texcoord,normal,tangent|pos,texcoord,normal,tangent|..
        pipelinVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
        pipelinVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
        pipelinVertexInputStateCreateInfo.vertexAttributeDescriptionCount = 1;
        pipelinVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
        pipelinVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription;
        //glViewport,glScissor
        VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {};
        pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
        pipelineDynamicStateCreateInfo.dynamicStateCount = 0;
        pipelineDynamicStateCreateInfo.pDynamicStates = nullptr;//viewport,scissor
        VkViewport viewport = {};//ndc -> viewport : -1~1 -> 0.0 ~ canvas size
        viewport.x = 0.0f;
        viewport.y = 720.0f;
        viewport.width = 1280.0f;
        viewport.height = -720.0f;
        viewport.maxDepth = 1.0f;
        viewport.minDepth = 0.0f;//-1~1
        VkRect2D scissor = {};
        scissor.offset.x = 0;
        scissor.offset.y = 0;
        scissor.extent.width = 1280u;
        scissor.extent.height = 720u;
        VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {};
        pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
        pipelineViewportStateCreateInfo.viewportCount = 1;
        pipelineViewportStateCreateInfo.scissorCount = 1;
        pipelineViewportStateCreateInfo.pViewports = &viewport;
        pipelineViewportStateCreateInfo.pScissors = &scissor;

        VkPipelineInputAssemblyStateCreateInfo pipelineIAStateCreateInfo = {};
        pipelineIAStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
        pipelineIAStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

        VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {};
        pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
        pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;
        pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;//stream out,transform feedback
        pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
        pipelineRasterizationStateCreateInfo.lineWidth = 1.0f;
        pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
        pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
        pipelineRasterizationStateCreateInfo.depthBiasSlopeFactor = 0.0f;//
        pipelineRasterizationStateCreateInfo.depthBiasConstantFactor = 0.0f;
        pipelineRasterizationStateCreateInfo.depthBiasClamp = 0.0f;
        pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE;

        VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {};
        pipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
        pipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
        pipelineMultisampleStateCreateInfo.minSampleShading = 1.0f;

        VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {};
        pipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
        pipelineDepthStencilStateCreateInfo.depthTestEnable = true;
        pipelineDepthStencilStateCreateInfo.depthWriteEnable = true;
        pipelineDepthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
        pipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = false;
        pipelineDepthStencilStateCreateInfo.minDepthBounds = 0.0f;
        pipelineDepthStencilStateCreateInfo.maxDepthBounds = 1.0f;
        pipelineDepthStencilStateCreateInfo.stencilTestEnable = false;
        pipelineDepthStencilStateCreateInfo.front = {};
        pipelineDepthStencilStateCreateInfo.back = {};

        VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
        pipelineColorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
        pipelineColorBlendAttachmentState.blendEnable = false;

        VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {};
        pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
        pipelineColorBlendStateCreateInfo.attachmentCount = 1;
        pipelineColorBlendStateCreateInfo.blendConstants[0] = 0.0f;
        pipelineColorBlendStateCreateInfo.blendConstants[1] = 0.0f;
        pipelineColorBlendStateCreateInfo.blendConstants[2] = 0.0f;
        pipelineColorBlendStateCreateInfo.blendConstants[3] = 0.0f;
        pipelineColorBlendStateCreateInfo.logicOpEnable = false;
        pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState;

        VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo[2];
        pipelineShaderStageCreateInfo[0] = {};
        pipelineShaderStageCreateInfo[0].sType=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        pipelineShaderStageCreateInfo[0].stage=VK_SHADER_STAGE_VERTEX_BIT;
        pipelineShaderStageCreateInfo[0].module=inShaders[0]->mShaderModule;
        pipelineShaderStageCreateInfo[0].pName="main";
        pipelineShaderStageCreateInfo[1] = {};
        pipelineShaderStageCreateInfo[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
        pipelineShaderStageCreateInfo[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
        pipelineShaderStageCreateInfo[1].module = inShaders[1]->mShaderModule;
        pipelineShaderStageCreateInfo[1].pName = "main";

        PipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
        PipelineInfo.renderPass = PSO->mRenderPass->GetHandle();
        PipelineInfo.stageCount = 2;//vertex->tcs->tes->geometry->fragment->
        PipelineInfo.basePipelineIndex = -1;
        PipelineInfo.pVertexInputState = &pipelinVertexInputStateCreateInfo;
        PipelineInfo.pDynamicState = &pipelineDynamicStateCreateInfo;
        PipelineInfo.pViewportState = &pipelineViewportStateCreateInfo;
        PipelineInfo.pInputAssemblyState = &pipelineIAStateCreateInfo;
        PipelineInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo;
        PipelineInfo.pMultisampleState = &pipelineMultisampleStateCreateInfo;
        PipelineInfo.pDepthStencilState = &pipelineDepthStencilStateCreateInfo;
        PipelineInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo;
        PipelineInfo.pStages = pipelineShaderStageCreateInfo;
        PipelineInfo.layout = PSO->mLayout->mPipelineLayout;
        CreateVKPipeline(PSO,inShaders,PipelineInfo,PSOCompileType);
        return true;
    }
    VkResult FVulkanPipelineStateCacheManager::CreateVKPipeline(FVulkanCGIGraphicPipelineState* PSO, VulkanShader* Shaders[5], const VkGraphicsPipelineCreateInfo& PipelineInfo, FGraphicsPipelineStateInitializer::EPSOPrecacheCompileType PSOCompileType)
    {
        VkResult ret = vkCreateGraphicsPipelines(mDevice->GetDevice(),nullptr,1,&PipelineInfo,nullptr,&PSO->mPipeline);
        return ret;
    }
}
